/**
**************************************************************************************
*Palisma - Secrets of the Illuminati is an open-source 2D RPG                        *
*Copyright (C) 2006, Tony Sparks                                                     *
*                                                                                    *
*This library is free software; you can redistribute it and/or                       *
*modify it under the terms of the GNU Lesser General Public                          *
*License as published by the Free Software Foundation; either                        *
*version 2.1 of the License, or (at your option) any later version.                  *
*                                                                                    *
*This library is distributed in the hope that it will be useful,                     *
*but WITHOUT ANY WARRANTY; without even the implied warranty of                      *
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                   *
*Lesser General Public License for more details.                                     *
*                                                                                    *
*You should have received a copy of the GNU Lesser General Public                    *
*License along with this library; if not, write to the Free Software                 *
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA      *
**************************************************************************************
*/

#include "StdAfx.h"
#include "MissionHolder.h"
#include "../kernel.h"
#include "../shared/MFile.h"
#include "DialogModel.h" // DialogEvent

extern Kernel* g_kernel;

#define TIME (g_kernel->GetTime())
#define PRINT(str)  (g_kernel->LPrintf( str ) )

/*-------------------------------------------
    Mission Holder 
---------------------------------------------*/

MissionHolder::MissionHolder(void) : IEventListener()
{
    EventManager::GetInstance()->AddListener(this);
    m_id = 0; // players ID (hacked)
}

MissionHolder::~MissionHolder(void)
{
    RemoveAll();
    EventManager::GetInstance()->RemoveListener(this);
    IEventListener::~IEventListener();
}

/** Mission is completed */
void MissionHolder::CompleteMission(const std::string &mission)
{
    if ( HasMission( mission ) )
    {
        GetMission( mission )->SetStatus( M_COMPLETE );
    }
}


/** Get a Mission */
Mission* MissionHolder::GetMission( const std::string &mission)
{
    if ( HasMission( mission ) )
    {
        return m_missions[ mission ];
    }
    return NULL;
}

/** Failed a mission */
void MissionHolder::FailedMission(const std::string &mission)
{
    if ( HasMission( mission ) )
    {
        GetMission( mission )->SetStatus( M_FAILED );
    }
}

/** Retrieve the status of a mission */
int MissionHolder::GetMissionStatus(const std::string &mission)
{
    if ( HasMission( mission ) )
    {
        return GetMission( mission )->GetStatus();
    }
    return -1;
}

/** Has mission */
bool MissionHolder::HasMission( const std::string &mission)
{
    return m_missions.find( mission ) != m_missions.end();
}


/** Remove a mission */
void MissionHolder::RemoveMission( Mission* m )
{
    type_Missions::iterator it = m_missions.begin();
    for( ; it != m_missions.end(); it++ )
    {
        if ( it->second == m )
        {
            delete m;
            m_missions.erase( it );
            return;
        }
    }
}

/** Remove all */
void MissionHolder::RemoveAll()
{
    type_Missions::iterator it = m_missions.begin();
    for( ; it != m_missions.end(); it++ )
    {
        delete it->second;
    }
    m_missions.clear();
}

/** Get the Mission for storage */
bool MissionHolder::HandleEvent( IEvent* e )
{
    Mission* m = e->GetData<MissionEvent>()->m_mission;
    switch( e->GetType() ) 
    {
    case EVT_ADD_MISSION:
        
        // TODO- check ID
        AddMission( m );
        PRINT( ("received event from " + m->GetName()).c_str() ); 
    break;
    case EVT_RM_MISSION:
        RemoveMission( m );
        PRINT( ("remove event from " + m->GetName()).c_str() );
    break;
    }
    return 0;
}



/*-------------------------------------------
    Mission Dispatcher
---------------------------------------------*/


MissionDispatcher::MissionDispatcher()
{
    EventManager::GetInstance()->AddListener(this);
}

MissionDispatcher::~MissionDispatcher()
{
    EventManager::GetInstance()->RemoveListener(this);
}

/** Create a mission */
Mission* MissionDispatcher::CreateMission( const std::string &f )
{
    MFile file;
    if ( file.Open( f ) )
    {
        g_kernel->LPrintf( ("Could not find: " + f).c_str() );
        return NULL;
    }

    Mission* mission = new Mission;

    mission->SetName( file.ReadNext(":") );
    mission->SetObjective( file.ReadNext(":", false ) );
    mission->SetRules( file.ReadNext(":") );
    mission->SetStatus( M_INCOMPLETE );

    m_assignedMissions[ f ] = mission;
    return mission;
}


/** Handle an event */
bool MissionDispatcher::HandleEvent( IEvent* e )
{
    switch( e->GetData<DialogEvent>()->m_response )
    {
    // first response is acceptance
        // TODO - Make this more adaptable
    case D_RESPONSE1:
        Mission* mission = NULL;
        std::string &s = e->GetData<DialogEvent>()->mission;
        if ( !IsAssigned(s) )
        {
            mission = CreateMission( s );
 
            IEvent evt( EVT_ADD_MISSION, TIME, new MissionEvent( mission, 1 ), LT_MISSION_HOLDER );
            EventManager::GetInstance()->TriggerEvent( evt );
        }
        break;
    };
    return false;
}


/** Check to see if this mission was already assigned */
bool MissionDispatcher::IsAssigned(const std::string &mission )
{
    return m_assignedMissions.find( mission ) != m_assignedMissions.end();
}

/** Get the next mission */
Mission* MissionDispatcher::GetNextMission()
{
    return NULL;
}

/** Has completed a mission */
bool MissionDispatcher::HasCompleted()
{
    return false;
}